package com.dkts.oil.test.road;

import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.linearref.LengthIndexedLine;
import org.opengis.feature.simple.SimpleFeature;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.util.*;

public class ShippingRouteToOSM {

    static class PortWithIndex {
        Point point;
        double index;
        Coordinate foot;
        String name;

        public PortWithIndex(Point point, double index, Coordinate foot, String name) {
            this.point = point;
            this.index = index;
            this.foot = foot;
            this.name = name;
        }
    }

    public static void main(String[] args) throws Exception {
        FeatureJSON fjson = new FeatureJSON();
        GeometryFactory gf = new GeometryFactory();

        // 读取中心线
        FeatureIterator<SimpleFeature> lineIt = fjson.readFeatureCollection(new FileReader("D:\\dkSpace\\油库规划\\部署相关\\水路规划\\长江珠江路网.geojson")).features();
        Geometry centerGeom = null;
        if (lineIt.hasNext()) {
            centerGeom = (Geometry) lineIt.next().getDefaultGeometry();
        }
        lineIt.close();

        LineString centerLine;
        if (centerGeom instanceof MultiLineString) {
            List<Coordinate> coords = new ArrayList<>();
            MultiLineString mls = (MultiLineString) centerGeom;
            for (int i = 0; i < mls.getNumGeometries(); i++) {
                LineString ls = (LineString) mls.getGeometryN(i);
                Collections.addAll(coords, ls.getCoordinates());
            }
            centerLine = gf.createLineString(coords.toArray(new Coordinate[0]));
        } else {
            centerLine = (LineString) centerGeom;
        }

        LengthIndexedLine indexedLine = new LengthIndexedLine(centerLine);

        // 读取港口点及名称
        FeatureIterator<SimpleFeature> portIt = fjson.readFeatureCollection(new FileReader("src/main/resources/长江珠江路网.geojson")).features();
        List<PortWithIndex> portsWithIndex = new ArrayList<>();
        while (portIt.hasNext()) {
            SimpleFeature feature = portIt.next();
            Point portPt = (Point) feature.getDefaultGeometry();
            String name = (String) feature.getAttribute("name");
            double index = indexedLine.project(portPt.getCoordinate());
            Coordinate foot = indexedLine.extractPoint(index);
            portsWithIndex.add(new PortWithIndex(portPt, index, foot, name));
        }
        portIt.close();

        // 排序港口按投影索引
        portsWithIndex.sort(Comparator.comparingDouble(p -> p.index));

        // 串联完整路径：航线 → 垂足 → 港口 → 垂足 → 航线
        List<Coordinate> routeCoords = new ArrayList<>();
        Coordinate[] lineCoords = centerLine.getCoordinates();
        int portCursor = 0;

        for (int i = 0; i < lineCoords.length - 1; i++) {
            Coordinate c1 = lineCoords[i];
            double segStartIndex = indexedLine.project(c1);
            double segEndIndex = indexedLine.project(lineCoords[i + 1]);

            if (routeCoords.isEmpty()) {
                routeCoords.add(c1);
            }

            while (portCursor < portsWithIndex.size()) {
                PortWithIndex port = portsWithIndex.get(portCursor);
                if (port.index >= segStartIndex && port.index <= segEndIndex) {
                    routeCoords.add(port.foot);
                    routeCoords.add(port.point.getCoordinate());
                    routeCoords.add(port.foot);
                    portCursor++;
                } else {
                    break;
                }
            }

            routeCoords.add(lineCoords[i + 1]);
        }

        LineString finalRoute = gf.createLineString(routeCoords.toArray(new Coordinate[0]));

        // 导出 OSM 文件
        exportLineAndPortsToOSM(finalRoute, portsWithIndex, "src/main/resources/shipping_route_ports.osm");
    }

    // 导出 OSM：主航线+港口点+名称
    public static void exportLineAndPortsToOSM(LineString lineString, List<PortWithIndex> ports, String filePath) throws Exception {
        PrintWriter writer = new PrintWriter(new FileWriter(filePath));
        DecimalFormat df = new DecimalFormat("#.######");

        writer.println("<?xml version='1.0' encoding='UTF-8'?>");
        writer.println("<osm version='0.6' generator='custom-shipping-exporter'>");

        // 航线坐标点 node
        long nodeId = -1;
        Coordinate[] coords = lineString.getCoordinates();
        Map<String, Long> coordToId = new HashMap<>();

        for (Coordinate c : coords) {
            String key = c.x + "," + c.y;
            if (!coordToId.containsKey(key)) {
                writer.println("  <node id='" + nodeId + "' lat='" + df.format(c.y) + "' lon='" + df.format(c.x) + "' />");
                coordToId.put(key, nodeId);
                nodeId--;
            }
        }

        // 港口点 node
        long portIdStart = -100000;
        for (PortWithIndex port : ports) {
            writer.println("  <node id='" + portIdStart + "' lat='" + df.format(port.point.getY()) +
                    "' lon='" + df.format(port.point.getX()) + "'>");
            writer.println("    <tag k='name' v='" + port.name + "' />");
            writer.println("    <tag k='type' v='port' />");
            writer.println("  </node>");
            portIdStart--;
        }

        // 航线 way
        writer.println("  <way id='-500'>");
        for (Coordinate c : coords) {
            String key = c.x + "," + c.y;
            writer.println("    <nd ref='" + coordToId.get(key) + "' />");
        }
        writer.println("    <tag k='type' v='shipping_route' />");
        writer.println("    <tag k='name' v='长江航运航线' />");
        writer.println("  </way>");

        writer.println("</osm>");
        writer.close();

        System.out.println("✔ 航线+港口+名称 OSM 导出完成，保存到 " + filePath);
    }
}
